jsmiscdir = $(pkgdatadir)/js/misc
dist_jsmisc_DATA = \
- docInfo.js
+ docInfo.js \
+ format.js
--- /dev/null
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+/*
+ * This function is intended to extend the String object and provide
+ * an String.format API for string formatting.
+ * It has to be set up using String.prototype.format = Format.format;
+ * Usage:
+ * "somestring %s %d".format('hello', 5);
+ * It supports %s, %d and %f, for %f it also support precisions like
+ * "%.2f".format(1.526)
+ */
+
+function format() {
+ let str = this;
+ let i = 0;
+ let args = arguments;
+
+ return str.replace(/%(?:\.([0-9]+))?(.)/g, function (str, precisionGroup, genericGroup) {
+
+ if (precisionGroup != '' && genericGroup != 'f')
+ throw new Error("Precision can only be specified for 'f'");
+
+ switch (genericGroup) {
+ case '%':
+ return '%';
+ break;
+ case 's':
+ return args[i++].toString();
+ break;
+ case 'd':
+ return parseInt(args[i++]);
+ break;
+ case 'f':
+ if (precisionGroup == '')
+ return parseFloat(args[i++]);
+ else
+ return parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
+ break;
+ default:
+ throw new Error('Unsupported conversion character %' + genericGroup);
+ }
+
+ });
+}
const Tweener = imports.ui.tweener;
+const Format = imports.misc.format;
+
// "monkey patch" in some varargs ClutterContainer methods; we need
// to do this per-container class since there is no representation
// of interfaces in Javascript
function init() {
Tweener.init();
+ String.prototype.format = Format.format;
}
interactive/scrolling.js \
interactive/table.js \
testcommon/border-image.png \
- testcommon/ui.js
+ testcommon/ui.js \
+ unit/format.js
EXTRA_DIST += $(TEST_JS)
TEST_MISC = \
--- /dev/null
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+/*
+ * Test cases for the Format module
+ */
+
+const JsUnit = imports.jsUnit;
+const assertEquals = JsUnit.assertEquals;
+const assertRaises = JsUnit.assertRaises;
+
+// We can't depend on environment.js to set up the String.prototype.format,
+// because the tests run in one JS context, and the imports run in the GJS
+// "load context" which has its own copy of the String class
+const Format = imports.misc.format;
+String.prototype.format = Format.format;
+
+// Test common usage and %% handling
+assertEquals("foo", "%s".format('foo'));
+assertEquals("%s", "%%s".format('foo'));
+assertEquals("%%s", "%%%%s".format('foo'));
+assertEquals("foo 5", "%s %d".format('foo', 5));
+assertEquals("8", "%d".format(8));
+assertEquals("2.58 6.96", "%f %.2f".format(2.58, 6.958));
+
+// Precision is only allowed for %f
+assertRaises(function() { "%.2d".format(5.21) });
+
+// Wrong conversion character ' '
+assertRaises( function() { "%s is 50% done".format('foo') });